package com.unnet.yjs.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.unnet.yjs.base.ContainerProperties;
import com.unnet.yjs.entity.Rescource;
import com.unnet.yjs.exception.MyException;
import com.unnet.yjs.service.ResourceService;
import com.unnet.yjs.service.UploadService;
import com.unnet.yjs.util.QETag;
import com.unnet.yjs.util.RestResponse;
import com.xiaoleilu.hutool.util.RandomUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Decoder;

import javax.annotation.Resource;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;

/**
 * Email: love1208tt@foxmail.com
 * Copyright (c)  2019. missbe
 * @author lyg   19-7-1 下午9:55
 *
 *
 **/
@Service("localService")
public class LocalUploadServiceImpl implements UploadService {
    private static final Logger LOGGER = LoggerFactory.getLogger(LocalUploadServiceImpl.class);
    @Resource
    private ContainerProperties containerProperties;
    @Resource
    private ResourceService resourceService;

    /**
     * 文件上传方法
     *
     * @param file MultipartFile文件对象
     * @return 文件在云上的地址
     */
    @Override
    public String upload(MultipartFile file, String directoryName,Map<String,Object> map) throws IOException, NoSuchAlgorithmException {
        ///计算文件hash值
        QETag tag = new QETag();
        String hash = tag.calcETag(file);

        String fileName;
        String isRename = (String) map.get("isRename");
        ///判断文件是否重命名
        if(Boolean.TRUE.equals(Boolean.valueOf(isRename))){
            String extName = file.getOriginalFilename().substring(
                    Objects.requireNonNull(file.getOriginalFilename()).lastIndexOf("."));
            fileName = UUID.randomUUID() + extName;
        }else{
            fileName = file.getOriginalFilename();
        }

        EntityWrapper<Rescource> wrapper = new EntityWrapper<>();
        wrapper.eq("hash", hash);
        wrapper.eq("source", "local");
        wrapper.eq("is_rename", Boolean.valueOf(isRename));
        Rescource rescource = resourceService.selectOne(wrapper);
        if (rescource != null) {
            LOGGER.info("current local file already save, web url is " + rescource.getWebUrl());
            return rescource.getWebUrl();
        }

        String contentType = file.getContentType();
        String sb = ResourceUtils.getURL("classpath:").getPath();
        StringBuilder directory = new StringBuilder();
        if (directoryName == null || directoryName.isEmpty()) {
            directory.append("static/upload/");
        } else {
            directory.append("static/upload/").append(directoryName).append("/");
        }
        String filePath = sb + directory.toString();
        File targetFile = new File(filePath);
        if (!targetFile.exists()) {
            ///递归创建目录
            targetFile.mkdirs();
        }

        FileOutputStream out = new FileOutputStream(filePath + fileName);
        byte[] data = file.getBytes();
        out.write(data);
        out.flush();
        out.close();

        LOGGER.info("local store file:" + file.getOriginalFilename() + " success. save file name:" + fileName);

        String webUrl = "http://" + containerProperties.getFileServerContext() +  "/" + directory.toString() + fileName;
        rescource = new Rescource();
        rescource.setFileName(file.getOriginalFilename());
        rescource.setFileSize(new java.text.DecimalFormat("#.##").format(file.getSize() / 1024) + "kb");
        rescource.setHash(hash);
        rescource.setFileType(contentType);
        rescource.setWebUrl(webUrl);
        rescource.setSource("local");
        rescource.setAreaId(map.get("AREA_ID").toString());
        rescource.setOriginalNetUrl(webUrl);
        rescource.setRemarks(file.getOriginalFilename());
        rescource.setRename(Boolean.valueOf(isRename));
        resourceService.insert(rescource);
        return webUrl;
    }

    @Override
    public Boolean delete(List<String> fileNames) {
        return null;
    }

    @Override
    public String upload(MultipartFile file, Map<String,Object> map) throws IOException, NoSuchAlgorithmException {
        return upload(file, "image",map);
    }


    @Override
    public Boolean delete(String path) {
        path = path.replaceFirst("/", "classpath:");
        File file = new File(path);
        if (file.exists()) {
            file.delete();
            return true;
        } else {
            return false;
        }
    }

    @Override
    public String uploadNetFile(String url) throws IOException, NoSuchAlgorithmException {
        Rescource rescource = new Rescource();
        EntityWrapper<RestResponse> wrapper = new EntityWrapper<>();
        wrapper.eq("original_net_url", url);
        wrapper.eq("source", "local");
        rescource = rescource.selectOne(wrapper);
        if (rescource != null) {
            return rescource.getWebUrl();
        }
        String extName = url.substring(url.lastIndexOf("."));
        String fileName = UUID.randomUUID() + extName;
        String filePath = ResourceUtils.getURL("classpath:").getPath() + "static/upload/";
        File uploadDir = new File(filePath);
        if (!uploadDir.exists()) {
            uploadDir.mkdirs();
        }
        URL neturl = new URL(url);
        HttpURLConnection conn = (HttpURLConnection) neturl.openConnection();
        conn.connect();
        BufferedInputStream br = new BufferedInputStream(conn.getInputStream());
        byte[] buf = new byte[1024];
        int len;
        FileOutputStream out = new FileOutputStream(filePath + fileName);
        while ((len = br.read(buf)) > 0) {
            out.write(buf, 0, len);
        }
        File targetFile = new File(filePath + fileName);
        String webUrl = "";
        if (targetFile.exists()) {
            webUrl = "/static/upload/" + fileName;
            rescource = new Rescource();
            QETag tag = new QETag();
            rescource.setFileName(fileName);
            rescource.setFileSize(new java.text.DecimalFormat("#.##").format(br.read(buf) / 1024) + "kb");
            rescource.setHash(tag.calcETag(targetFile));
            rescource.setFileType(StringUtils.isBlank(extName) ? "unknown" : extName);
            rescource.setWebUrl(webUrl);
            rescource.setOriginalNetUrl(url);
            rescource.setSource("local");
            rescource.insert();
        }
        br.close();
        out.flush();
        out.close();
        conn.disconnect();
        return webUrl;
    }

    @Override
    public String uploadLocalImg(String localPath) {
        File file = new File(localPath);
        if (!file.exists()) {
            throw new MyException("本地文件不存在");
        }
        QETag tag = new QETag();
        String hash = null;
        try {
            hash = tag.calcETag(file);
        } catch (IOException | NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        Rescource rescource = new Rescource();
        EntityWrapper<RestResponse> wrapper = new EntityWrapper<>();
        wrapper.eq("hash", hash);
        rescource = rescource.selectOne(wrapper);
        if (rescource != null) {
            return rescource.getWebUrl();
        }
        StringBuffer sb = null;
        try {
            sb = new StringBuffer(ResourceUtils.getURL("classpath:").getPath());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        assert sb != null;
        String filePath = sb.append("static/upload/").toString();
        StringBuilder name = new StringBuilder(RandomUtil.randomUUID());
        StringBuilder returnUrl = new StringBuilder("/static/upload/");
        String extName;
        extName = file.getName().substring(
                file.getName().lastIndexOf("."));
        sb.append(name).append(extName);
        File uploadDir = new File(filePath);
        if (!uploadDir.exists()) {
            uploadDir.mkdir();
        }
        try {
            InputStream input = new FileInputStream(file);
            byte[] buf = new byte[input.available()];
            int len;
            FileOutputStream out = new FileOutputStream(sb.toString());
            while ((len = input.read(buf)) > 0) {
                out.write(buf, 0, len);
            }
            input.close();
            out.flush();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        returnUrl.append(name).append(extName);
        return returnUrl.toString();
    }

    @Override
    public String uploadBase64(String base64) {
        StringBuilder webUrl = new StringBuilder("/static/upload/");
        BASE64Decoder decoder = new BASE64Decoder();
        try {
            //Base64解码
            byte[] b = decoder.decodeBuffer(base64);
            //调整异常数据
            for (int i = 0; i < b.length; ++i) {
                if (b[i] < 0) {
                    b[i] += 256;
                }
            }
            //生成jpeg图片
            String filePath = ResourceUtils.getURL("classpath:").getPath() + "static/upload/";
            File targetFileDir = new File(filePath);
            if (!targetFileDir.exists()) {
                targetFileDir.mkdirs();
            }
            StringBuilder sb = new StringBuilder(filePath);
            StringBuilder fileName = new StringBuilder(RandomUtil.randomUUID());
            sb.append(fileName);
            sb.append(".jpg");
            //新生成的图片
            String imgFilePath = sb.toString();
            OutputStream out = new FileOutputStream(imgFilePath);
            out.write(b);
            out.flush();
            out.close();
            return webUrl.append(sb).toString();
        } catch (Exception e) {
            return null;
        }
    }
}
